#include "libtimer.h" 

ptimer_t * 
new_timer (void)
{
    ptimer_t *ret_val = NULL;

    ret_val = (ptimer_t *) safe_malloc (sizeof (ptimer_t));
    ret_val->active = TRUE;

    GET_TIME (ret_val->start);

    return (ret_val);
}

void 
destroy_timer (ptimer_t *timer)
{
    if (timer != NULL) {
        free (timer);
        timer = NULL;
    }
}

void 
timer_start (ptimer_t *timer)
{
    if (timer == NULL) {
        fprintf (stderr, "ERROR: timer == NULL!\n");
        exit (EXIT_FAILURE);
    }

    timer->active = TRUE;
    GET_TIME (timer->start);
}

void 
timer_stop (ptimer_t *timer)
{
    if (timer == NULL) {
        fprintf (stderr, "ERROR: timer == NULL!\n");
        exit (EXIT_FAILURE);
    }

    timer->active = FALSE;
    GET_TIME (timer->end);
}

void 
timer_reset (ptimer_t *timer)
{
    if (timer == NULL) {
        fprintf (stderr, "ERROR: timer == NULL!\n");
        exit (EXIT_FAILURE);
    }

    GET_TIME (timer->end);
}

void 
timer_continue (ptimer_t *timer)
{
    struct timeval elapsed;

    if (timer == NULL) {
        fprintf (stderr, "ERROR: timer == NULL!\n");
        exit (EXIT_FAILURE);
    } else if (timer->active == TRUE) {
        fprintf (stderr, "ERROR: timer already active!\n");
        exit (EXIT_FAILURE);
    }

    if (timer->start.tv_usec > timer->end.tv_usec) {
        timer->end.tv_usec += USEC_PER_SEC;
        timer->end.tv_sec--;
    }

    elapsed.tv_usec = timer->end.tv_usec - timer->start.tv_usec;
    elapsed.tv_sec = timer->end.tv_sec - timer->start.tv_sec;
    GET_TIME (timer->start);

    if (timer->start.tv_usec < elapsed.tv_usec) {
        timer->start.tv_usec += USEC_PER_SEC;
        timer->start.tv_sec--;
    }

    timer->start.tv_usec -= elapsed.tv_usec;
    timer->start.tv_sec -= elapsed.tv_sec;
    timer->active = TRUE;
}


double 
timer_elapsed (ptimer_t *timer)
{
    double total;
    struct timeval elapsed;

    if (timer == NULL) {
        fprintf (stderr, "ERROR: timer == NULL!\n");
        exit (EXIT_FAILURE);
    }

    if (timer->active) {
        GET_TIME (timer->end);
    }

    if (timer->start.tv_usec > timer->end.tv_usec) {
      timer->end.tv_usec += USEC_PER_SEC;
      timer->end.tv_sec--;
    }

    elapsed.tv_usec = timer->end.tv_usec - timer->start.tv_usec;
    elapsed.tv_sec = timer->end.tv_sec - timer->start.tv_sec;

    total = elapsed.tv_sec + ((double) elapsed.tv_usec / 1e6);
    if (total < 0) {
        total = 0;
    }

    return  (total);
}


void
delete_time (void *data)
{
  value_t *rv = (value_t *)data;
  if (rv) {
    free (rv);
  }
  return;
}


double
calculate_avg (double* times,int n)
{
  int i;
  double sum;

  sum = 0;
  for(i=0; i<n; i++)
  {
    sum = sum + times[i];
  }
  
  return (sum/n);
}


double
calculate_stddev (double* times,int n)
{
  int i;
  double avg, tmp;

  i = 0;
  avg = calculate_avg(times, n);
  tmp = 0; 

  for(i=0; i<n; i++)
  {
    tmp = tmp + pow(times[i] - avg, 2); 
  }

  tmp = tmp * (1/n);
  return sqrt(tmp);
}

